/*
 * @(#)CryptUtil.java	1.0 Apr 26, 2008
 *
 *	The MIT License
 *
 *	Copyright (c) 2008 Malachi de AElfweald <malachid@gmail.com>
 *
 *	Permission is hereby granted, free of charge, to any person obtaining a copy
 *	of this software and associated documentation files (the "Software"), to deal
 *	in the Software without restriction, including without limitation the rights
 *	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *	copies of the Software, and to permit persons to whom the Software is
 *	furnished to do so, subject to the following conditions:
 *
 *	The above copyright notice and this permission notice shall be included in
 *	all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *	THE SOFTWARE.
 */
package org.eoti.security.crypt;

import org.eoti.io.encoding.Base64Encoder;
import org.eoti.io.encoding.HexEncoder;
import org.eoti.io.encoding.Rot13Encoder;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.SecretKey;
import javax.crypto.spec.PBEParameterSpec;
import javax.crypto.spec.PBEKeySpec;

public class CryptUtil
{
	public static String encryptPassword(String password)
	throws CryptException
	{
		password = password.trim();
		//return base64Encode(cipher(createCipher(password),password));
		return JCrypt.crypt(password, password);
	}

	public static boolean isPasswordCorrect(String guess, String encrypted)
	throws CryptException
	{
		guess = guess.trim();
		encrypted = encrypted.trim();
		return encrypted.equals(encryptPassword(guess));
	}

	public static Cipher createCipher(String password)
	throws CryptException
	{
		return createCipher(password, password);
	}

	public static Cipher createCipher(String password, String salt)
	throws CryptException
	{
		return createCipher(password, salt, 20);
	}

	public static Cipher createCipher(String password, String salt, int iterationCount)
	throws CryptException
	{
		try{
		    char[] pwd = password.toCharArray();
		    byte[] slt = correctSalt(salt);

		    PBEParameterSpec paramSpec = new PBEParameterSpec(slt, iterationCount);
		    PBEKeySpec keySpec = new PBEKeySpec(pwd);
		    SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
		    SecretKey key = keyFac.generateSecret(keySpec);
		    Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");
		    cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);

			return cipher;
	    }catch (Exception e) {
	    	throw new CryptException("Unable to create cipher.", e);
	    }
	}

	protected static byte[] correctSalt(String salt)
	{
		if(salt.length() < 8)
			return correctSalt(salt + salt);

		if(salt.length() > 8)
			salt = salt.substring(0, 8);

		return salt.getBytes();
	}

	public static String cipher(Cipher cipher, String clearText)
	throws CryptException
	{
		try{
			return new String(cipher.doFinal(clearText.getBytes()));
	    }catch (Exception e) {
			throw new CryptException("Can not cipher text.", e);
	    }
	}

	public static String base64Encode(String clearText)
	{
//	    return (new sun.misc.BASE64Encoder().encode(clearOrCipherText.getBytes()));
		return base64Encode(clearText.getBytes());
	}

	public static String base64Encode(byte[] clearBytes)
	{
		return Base64Encoder.encode(clearBytes);
	}

	public static byte[] base64Decode(String cipherText)
	{
		return Base64Encoder.decode(cipherText);
	}

	public static String hexEncode(String clearText)
	{
		return hexEncode(clearText.getBytes());
	}

	public static String hexEncode(byte[] clearBytes)
	{
		return HexEncoder.encode(clearBytes);
	}

	public static byte[] hexDecode(String cipherText)
	{
		return HexEncoder.decode(cipherText);
	}

	public static String rot13Encode(String clearText)
	{
		return Rot13Encoder.encode(clearText);
	}

	public static String rot13Decode(String cipherText)
	{
		return Rot13Encoder.decode(cipherText);
	}
}